﻿using System;
using System.Collections.Generic;
using System.Text;

using ET;
using Marx;

namespace Demo
{
    public abstract class PlayerModel : DBModel
    {
    }

    public abstract class PlayerModelInfo<T> : PlayerInfo, IDatabase where T : PlayerModel, new()
    {
        public virtual string DBCollectionName => this.GetType().Name;
        public abstract bool ImediateSave { get; }
        public bool IsDirty => Model.IsDirty;

        protected T Model;

        public PlayerModelInfo()
        {
        }

        public void SetDirty()
        {
            if (ImediateSave)
            {
                SaveToDB();
                return;
            }

            if (IsDirty)
            {
                return;
            }

            Owner.DirtyQueue.Push(Model, DBCollectionName);
        }

        public void SetDirty(long delay)
        {
            if (IsDirty)
            {
                return;
            }

            Owner.DirtyQueue.Push(Model, DBCollectionName, delay);
        }

        public void SaveToDB()
        {
            DoSave().Coroutine();
        }

        private async ETTask DoSave()
        {
            try
            {
                await Model.Save(Owner.DB, DBCollectionName);
            }
            catch (Exception exception)
            {
                Log.Error(exception.Message);
                Log.Error("Player [" + Id.ToString() + "] save model [" + this.GetType().Name + "] failed..");
            }
        }

        public async ETTask LoadFromDB()
        {
            try
            {
                Model = await Owner.DB.Query<T>(PlayerId, DBCollectionName);
                if (Model == null)
                {
                    Model = new T();
                    Model.Id = PlayerId;
                }
            }
            catch (Exception e)
            {
                Log.Error("Player [" + PlayerId.ToString() + "] load model [" + typeof(T).Name + "] failed..");
                throw e;
            }
        }

        public virtual async ETTask OnDBLoaded()
        {
            await ETTask.CompletedTask;
        }

        public virtual async ETTask Destroy()
        {
            if (IsDirty)
            {
                await DoSave();
            }
        }
    }

}
